﻿using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using UnityEngine;
using System.IO;

/// <summary>
/// 统计函数、阶段执行时长
/// 使用方法：StartWatch和EndWatch必须匹配，最后调用WriteAll2Text会输出到文本，Editor下的路径为Assets/LoadingTimeLog.txt;手机路径为data/android/包名
/// [lvqq 20190420]
/// </summary>
///
namespace Yoozoo.UI.Tools
{
    public class StopwatchHelper
    {
        static string strWatchTimeLogPath = Application.persistentDataPath + "/LoadingTimeLog.txt";

        private static StopwatchHelper m_instance;

        public static StopwatchHelper Instance
        {
            get
            {
                if (m_instance == null)
                {
                    m_instance = new StopwatchHelper();
                }

                return m_instance;
            }
        }

        Stopwatch sw = new Stopwatch();
        Dictionary<string, SWItem> mDic = new Dictionary<string, SWItem>();

        StopwatchHelper()
        {
            sw.Start();
        }

        /// <summary>
        /// 统计开始时调用
        /// </summary>
        /// <param name="key">要统计的关键字</param>
        /// <param name="print">是否显示日志</param>
        [Conditional("DEBUG")]
        public void StartWatch(string key, bool print)
        {
            if (print)
            {
                Debug.LogFormat("[StopWatch]{0} start at frame {1}", key, Time.frameCount);
            }

            if (mDic.ContainsKey(key))
            {
                mDic[key].Start(sw.ElapsedMilliseconds);
            }
            else
            {
                mDic[key] = new SWItem(key, sw.ElapsedMilliseconds);
            }
        }


        /// <summary>
        /// 统计结束时调用
        /// </summary>
        /// <param name="key">要统计的关键字</param>
        /// <param name="print">是否输出debug信息</param>
        [Conditional("DEBUG")]
        public void EndWatch(string key, bool print = false)
        {
            if (mDic.ContainsKey(key))
            {
                SWItem item = mDic[key];
                item.End(sw.ElapsedMilliseconds);
                if (print)
                {
                    Debug.LogFormat("[StopWatch]{0} end at frame {1}", item, Time.frameCount);
                }
            }
        }

        /// <summary>
        /// 输出全部日志到文本
        /// </summary>
        [Conditional("DEBUG")]
        public void WriteAll2Text()
        {
#if UNITY_ANDROID && !UNITY_EDITOR
        IEnumerator itor = mDic.Values.GetEnumerator();
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("--------------StopwatchHelper begin-----------------");
        while (itor.MoveNext())
        {
            sb.AppendLine(((SWItem)itor.Current).ToString());
        }
        sb.AppendLine("--------------StopwatchHelper end-----------------");
        File.WriteAllText(strWatchTimeLogPath, sb.ToString(), Encoding.UTF8);
#endif
        }

        class SWItem
        {
            private List<long> startTime = new List<long>(); // 毫秒
            private List<long> endTime = new List<long>(); //毫秒
            private List<long> deltaTime = new List<long>(); //毫秒
            public string key;

            public SWItem(string key, long startTime)
            {
                this.key = key;
                Start(startTime);
            }

            public void Start(long time)
            {
                startTime.Add(time);
            }

            public void End(long time)
            {
                if (endTime.Count < startTime.Count)
                {
                    endTime.Add(time);
                    deltaTime.Add(time - startTime[endTime.Count - 1]);
                }
                else
                {
                    Debug.LogWarning("no start to match end:" + (key ?? ""));
                }
            }

            public override string ToString()
            {
                long totalTime = 0;
                for (int i = 0; i < deltaTime.Count; i++)
                {
                    totalTime += deltaTime[i];
                }

                if (deltaTime.Count > 0)
                {
                    float lastDeltaTime = deltaTime[deltaTime.Count - 1] / 1000.0f;
                    float averageDeltaTime = totalTime / 1000.0f / deltaTime.Count;
                    return $"{key}: {lastDeltaTime:00.00} s, aver. {averageDeltaTime:00.00} s, count: {deltaTime.Count}";
                }
                else
                {
                    return key + " StartWatch和EndWatch不匹配";
                }
            }
        }
    }
}
